#include "AC33Mxxx_conf.h"





// SPI
CSP_SPI_T		* const		SPI0		= (CSP_SPI_T *) SPI0_BASE_ADDRESS; 
CSP_SPI_T		* const		SPI1		= (CSP_SPI_T *) SPI1_BASE_ADDRESS; 





/**
*********************************************************************************************************
* @ Name : CSP_SPI_ConfigureGPIO 
*
* @ Parameters
*		- spi : SPI0, SPI1 
*		- master_slave : SPI_MASTER, SPI_SLAVE
*		- port_sel : SPI_PORTSEL_NORMAL, SPI_PORTSEL_STAR
*
*
*********************************************************************************************************
*/
void CSP_SPI_ConfigureGPIO (CSP_SPI_T * const spi, int master_slave, int port_sel)
{

	if ((spi == SPI0) && (port_sel == SPI_PORTSEL_NORMAL))
	{
	
		//------------------------------------------------------------------------------------
		// SPI0 (NORMAL)
		//
		//				PA12				SS0
		//				PA13				SCK0
		//				PA14				MOSI0
		//				PA15				MISO0
		//
		//				PAMR			@ address = 0x4000_1000
		//				PACR			@ address = 0x4000_1004
		//
		//
		//------------------------------------------------------------------------------------
		CSP_PCU_ConfigureFunction (PCU_A, PIN_12, PA12_MUX_SS0); 
		CSP_PCU_ConfigureFunction (PCU_A, PIN_13, PA13_MUX_SCK0); 
		CSP_PCU_ConfigureFunction (PCU_A, PIN_14, PA14_MUX_MOSI0); 
		CSP_PCU_ConfigureFunction (PCU_A, PIN_15, PA15_MUX_MISO0); 

		if (master_slave == SPI_MASTER)
		{
			CSP_PCU_Set_Direction_Type (PCU_A, PIN_12, PnCR_OUTPUT_PUSH_PULL); 
			CSP_PCU_Set_Direction_Type (PCU_A, PIN_13, PnCR_OUTPUT_PUSH_PULL); 
			CSP_PCU_Set_Direction_Type (PCU_A, PIN_14, PnCR_OUTPUT_PUSH_PULL); 
			CSP_PCU_Set_Direction_Type (PCU_A, PIN_15, PnCR_INPUT_LOGIC); 
		}
		else if (master_slave == SPI_SLAVE)
		{
			CSP_PCU_Set_Direction_Type (PCU_A, PIN_12, PnCR_INPUT_LOGIC); 
			CSP_PCU_Set_Direction_Type (PCU_A, PIN_13, PnCR_INPUT_LOGIC); 
			CSP_PCU_Set_Direction_Type (PCU_A, PIN_14, PnCR_INPUT_LOGIC); 
			CSP_PCU_Set_Direction_Type (PCU_A, PIN_15, PnCR_OUTPUT_PUSH_PULL); 
		}
		
		CSP_PCU_ConfigurePullup (PCU_A, PIN_12, PnPCR_PULLUP_DISABLE); 
		CSP_PCU_ConfigurePullup (PCU_A, PIN_13, PnPCR_PULLUP_DISABLE); 
		CSP_PCU_ConfigurePullup (PCU_A, PIN_14, PnPCR_PULLUP_DISABLE); 
		CSP_PCU_ConfigurePullup (PCU_A, PIN_15, PnPCR_PULLUP_DISABLE); 		


	}
	else if ((spi == SPI1) && (port_sel == SPI_PORTSEL_NORMAL))
	{
	
		//------------------------------------------------------------------------------------
		// SPI1 (NORMAL)
		//
		//				PD0				SS1
		//				PD1				SCK1
		//				PD2				MOSI1
		//				PD3				MISO1
		//
		//				PDMR			@ address = 0x4000_1300
		//				PDCR			@ address = 0x4000_1304
		//
		//
		//------------------------------------------------------------------------------------
		CSP_PCU_ConfigureFunction (PCU_D, PIN_0, PD0_MUX_SS1); 
		CSP_PCU_ConfigureFunction (PCU_D, PIN_1, PD1_MUX_SCK1); 
		CSP_PCU_ConfigureFunction (PCU_D, PIN_2, PD2_MUX_MOSI1); 
		CSP_PCU_ConfigureFunction (PCU_D, PIN_3, PD3_MUX_MISO1); 

		if (master_slave == SPI_MASTER)
		{
			CSP_PCU_Set_Direction_Type (PCU_D, PIN_0, PnCR_OUTPUT_PUSH_PULL); 
			CSP_PCU_Set_Direction_Type (PCU_D, PIN_1, PnCR_OUTPUT_PUSH_PULL); 
			CSP_PCU_Set_Direction_Type (PCU_D, PIN_2, PnCR_OUTPUT_PUSH_PULL); 
			CSP_PCU_Set_Direction_Type (PCU_D, PIN_3, PnCR_INPUT_LOGIC); 
		}
		else if (master_slave == SPI_SLAVE)
		{
			CSP_PCU_Set_Direction_Type (PCU_D, PIN_0, PnCR_INPUT_LOGIC); 
			CSP_PCU_Set_Direction_Type (PCU_D, PIN_1, PnCR_INPUT_LOGIC); 
			CSP_PCU_Set_Direction_Type (PCU_D, PIN_2, PnCR_INPUT_LOGIC); 
			CSP_PCU_Set_Direction_Type (PCU_D, PIN_3, PnCR_OUTPUT_PUSH_PULL); 
		}
		
		CSP_PCU_ConfigurePullup (PCU_D, PIN_0, PnPCR_PULLUP_DISABLE); 
		CSP_PCU_ConfigurePullup (PCU_D, PIN_1, PnPCR_PULLUP_DISABLE); 
		CSP_PCU_ConfigurePullup (PCU_D, PIN_2, PnPCR_PULLUP_DISABLE); 
		CSP_PCU_ConfigurePullup (PCU_D, PIN_3, PnPCR_PULLUP_DISABLE); 	


	}


}



/**
*********************************************************************************************************
* @ Name : CSP_SPI_Init 
*
* @ Parameters
*		- spi : SPI0, SPI1 
*		- master_slave : SPI_MASTER, SPI_SLAVE 
*		- p_config
*			# SS_enable			= SPI_SS_ENABLE, SPI_SS_DISABLE
*			# SS_auto_manual		= SPI_SS_AUTOMATIC, SPI_SS_MANUAL
*			# SS_polarity			= SPI_SS_ACTIVE_HIGH, SPI_SS_ACTIVE_LOW 
*			# SS_masking		= SPI_SS_MASKING, SPI_SS_NOT_MASKING
*
*			# msb_lsb_first		= SPI_MSB_FIRST, SPI_LSB_FIRST
*			# clock_polarity		= SPI_CPOL_ACTIVE_HIGH, SPI_CPOL_ACTIVE_LOW
*			# clock_phase			= SPI_CPHA_FRONT_HALF, SPI_CPHA_REAR_HALF 
*			# bit_size			= SPI_BITSIZE_8_BITS, SPI_BITSIZE_9_BITS, SPI_BITSIZE_16_BITS, SPI_BITSIZE_17_BITS
*
*			# baudrate			= 0x0001 ~ 0xFFFF
*
*			# start_len			= 1 ~ 255
*			# burst_len			= 1 ~ 255
*			# stop_len			= 1 ~ 255
*
*
*********************************************************************************************************
*/
void CSP_SPI_Init (CSP_SPI_T * const spi, int master_slave, SPI_CONFIG * p_config)
{

	UINT32				reg_val; 
	volatile int		i; 

	
	//----------------------------------------------------------------------------------------
	// buffer clear 
	//
	//				@ SP0CR = 0x4000_9004
	//				@ SP1CR = 0x4000_9104
	//
	//----------------------------------------------------------------------------------------
	// Technical Report
	//
	//				No need to clear buffer, because this will be done before transmitting data
	//
	//----------------------------------------------------------------------------------------
	CSP_SPI_SET_SPnCR (spi, (SPnCR_TXBC|SPnCR_RXBC)); 

	for (i=0; i<10; i++); 



	//----------------------------------------------------------------------------------------
	// config 
	//
	//				@ SP0CR = 0x4000_9004
	//				@ SP1CR = 0x4000_9104
	//
	//----------------------------------------------------------------------------------------

	reg_val = 0; 


	if (master_slave == SPI_MASTER) reg_val |= SPnCR_MS; 

	
	if (p_config->SS_enable == SPI_SS_ENABLE) reg_val |= SPnCR_SSMO; 
	if (p_config->SS_auto_manual == SPI_SS_MANUAL) reg_val |= SPnCR_SSMOD; 
	if (p_config->SS_polarity == SPI_SS_ACTIVE_HIGH) reg_val |= SPnCR_SSPOL; 
	if (p_config->SS_masking == SPI_SS_MASKING) reg_val |= SPnCR_SSMASK; 

	
	if (p_config->msb_lsb_first == SPI_MSB_FIRST) reg_val |= SPnCR_MSBF; 
	if (p_config->clock_polarity == SPI_CPOL_ACTIVE_LOW) reg_val |= SPnCR_CPOL; 
	if (p_config->clock_phase == SPI_CPHA_REAR_HALF) reg_val |= SPnCR_CPHA; 


	if (p_config->bit_size == SPI_BITSIZE_8_BITS) reg_val |= SPnCR_BITSZ_8_BITS; 
	else if (p_config->bit_size == SPI_BITSIZE_9_BITS) reg_val |= SPnCR_BITSZ_9_BITS; 
	else if (p_config->bit_size == SPI_BITSIZE_16_BITS) reg_val |= SPnCR_BITSZ_16_BITS; 
	else if (p_config->bit_size == SPI_BITSIZE_17_BITS) reg_val |= SPnCR_BITSZ_17_BITS; 
	

	CSP_SPI_SET_SPnCR(spi, reg_val); 

	
		
	//----------------------------------------------------------------------------------------
	// baud rate 
	//
	//				@ SP0BR = 0x4000_900C
	//				@ SP1BR = 0x4000_910C
	//
	//----------------------------------------------------------------------------------------	
	reg_val = (p_config->baudrate & 0x0000FFFF); 
	CSP_SPI_SET_SPnBR(spi, reg_val); 



	//----------------------------------------------------------------------------------------
	// interval 
	//
	//				@ SP0LR = 0x4000_9014
	//				@ SP1LR = 0x4000_9114
	//
	//----------------------------------------------------------------------------------------	
	reg_val = ((p_config->stop_len & 0xFF) << 16); 
	reg_val |= ((p_config->burst_len & 0xFF) << 8); 
	reg_val |= ((p_config->start_len & 0xFF) << 0); 

	CSP_SPI_SET_SPnLR(spi, reg_val); 

	


}


/**
*********************************************************************************************************
* @ Name : CSP_SPI_Enable
*
* @ Parameters
*		- spi : SPI0, SPI1 
*
*
*********************************************************************************************************
*/
void CSP_SPI_Enable (CSP_SPI_T * const spi)
{

	//----------------------------------------------------------------------------------------
	// SPnEN
	//
	//				@ SP0EN	= 0x4000_9010
	//				@ SP1EN = 0x4000_9110
	//
	//----------------------------------------------------------------------------------------
	CSP_SPI_SET_SPnEN(spi, SPnEN_ENABLE); 
	

}



/**
*********************************************************************************************************
* @ Name : CSP_SPI_Stop 
*
* @ Parameters
*		- spi : SPI0, SPI1 
*
*
*********************************************************************************************************
*/
void CSP_SPI_Stop (CSP_SPI_T * const spi)
{

	//----------------------------------------------------------------------------------------
	// SPnEN
	//
	//				@ SP0EN	= 0x4000_9010
	//				@ SP1EN = 0x4000_9110
	//
	//----------------------------------------------------------------------------------------
	CSP_SPI_SET_SPnEN(spi, 0); 


}



/**
*********************************************************************************************************
* @ Name : CSP_SPI_ConfigureInterrupt 
*
* @ Parameters
*		- spi : SPI0, SPI1 
*		- intr_mask : SPnCR_TXDIE, SPnCR_RXDIE, SPnCR_SSCIE, SPnCR_TXIE, SPnCR_RXIE
*		- enable : INTR_ENABLE, INTR_DISABLE 
*
*
*********************************************************************************************************
*/
void CSP_SPI_ConfigureInterrupt (CSP_SPI_T * const spi, UINT32 intr_mask, UINT32 enable)
{

	//----------------------------------------------------------------------------------------
	// disable interrupt 
	//
	//				@ SP0CR = 0x4000_9004
	//				@ SP1CR = 0x4000_9104
	//
	//----------------------------------------------------------------------------------------
	CSP_SPI_SET_SPnCR(spi, (CSP_SPI_GET_SPnCR(spi) & ~SPnCR_INTR_MASK)); 



	//----------------------------------------------------------------------------------------
	// clear interrupt flag 
	//
	//				@ SP0SR = 0x4000_9008
	//				@ SP1SR = 0x4000_9108
	//
	//----------------------------------------------------------------------------------------
	CSP_SPI_SET_SPnSR(spi, (CSP_SPI_GET_SPnSR(spi) & ~SPnSR_INTR_MASK)); 



	//----------------------------------------------------------------------------------------
	// enable interrupt 
	//
	//				@ SP0SR = 0x4000_9008
	//				@ SP1SR = 0x4000_9108
	//
	//----------------------------------------------------------------------------------------	
	if (enable == INTR_ENABLE)
	{
		CSP_SPI_SET_SPnCR(spi, (CSP_SPI_GET_SPnCR(spi) | (intr_mask & SPnCR_INTR_MASK))); 
	}


}


